"""Redis工具类，封装Redis的初始化、存储和读取操作"""

import redis
from typing import Optional, Any, List
from config.logger_config import get_default_logger
from config.sys_config import get_settings  # 导入系统配置

# 从系统配置中读取Redis配置
settings = get_settings()
logger = get_default_logger(__name__)

# 全局Redis客户端实例
_redis_client: Optional[redis.Redis] = None

class RedisKit:
    """Redis工具类，提供Redis连接管理和基本操作"""
    
    @staticmethod
    def _get_client() -> Optional[redis.Redis]:
        """获取Redis客户端实例
        
        Returns:
            redis.Redis: Redis客户端实例，如果连接失败则返回None
        """
        global _redis_client
        
        try:
            if _redis_client and RedisKit._is_connected():
                return _redis_client
                
            _redis_client = redis.Redis(
                host=settings.REDIS_HOST,
                port=settings.REDIS_PORT,
                db=settings.REDIS_DB,
                password=settings.REDIS_PASSWORD,
                decode_responses=False,
                socket_connect_timeout=5
            )
            # 测试连接
            _redis_client.ping()
            logger.info(f"成功连接到Redis服务器: {settings.REDIS_HOST}:{settings.REDIS_PORT}/db{settings.REDIS_DB}")
            return _redis_client
        except Exception as e:
            logger.error(f"Redis连接失败: {str(e)}")
            _redis_client = None
            return None
    
    @staticmethod
    def _is_connected() -> bool:
        """检查Redis连接是否活跃
        
        Returns:
            bool: 连接是否活跃
        """
        try:
            if _redis_client:
                _redis_client.ping()
                return True
        except:
            pass
        return False
    
    @staticmethod
    def set(key: str, value: str, expire: Optional[int] = None) -> bool:
        """设置键值对
        
        Args:
            key: 键名
            value: 值
            expire: 过期时间（秒），None表示永不过期
        
        Returns:
            bool: 操作是否成功
        """
        try:
            client = RedisKit._get_client()
            if client is None:
                return False
                
            if expire:
                client.set(key, value, ex=expire)
            else:
                client.set(key, value)
            return True
        except Exception as e:
            logger.error(f"Redis设置键值对失败: {str(e)}")
            return False
    
    @staticmethod
    def get(key: str) -> Optional[Any]:
        """获取键对应的值
        
        Args:
            key: 键名
        
        Returns:
            Any: 键对应的值，如果键不存在或操作失败则返回None
        """
        try:
            client = RedisKit._get_client()
            if client is None:
                return None
                    
            return client.get(key)
        except Exception as e:
            logger.error(f"Redis获取键值对失败: {str(e)}")
            return None
    
    @staticmethod
    def delete(key: str) -> bool:
        """删除键值对
        
        Args:
            key: 键名
        
        Returns:
            bool: 操作是否成功
        """
        try:
            client = RedisKit._get_client()
            if client is None:
                return False
                    
            client.delete(key)
            return True
        except Exception as e:
            logger.error(f"Redis删除键值对失败: {str(e)}")
            return False
    
    @staticmethod
    def exists(key: str) -> bool:
        """检查键是否存在
        
        Args:
            key: 键名
        
        Returns:
            bool: 键是否存在
        """
        try:
            client = RedisKit._get_client()
            if client is None:
                return False
                    
            return bool(client.exists(key))
        except Exception as e:
            logger.error(f"Redis检查键是否存在失败: {str(e)}")
            return False
    
    @staticmethod
    def keys(pattern: str) -> List[str]:
        """根据模式获取所有匹配的键
        
        Args:
            pattern: 键名模式，支持通配符(*, ?, [])
        
        Returns:
            List[str]: 匹配的键列表
        """
        try:
            client = RedisKit._get_client()
            if client is None:
                return []
            
            # 使用execute_command直接执行KEYS命令，避免类型问题
            matched_keys = client.execute_command('KEYS', pattern)
            # 处理字节类型键名
            result = []
            # 使用异常处理来绕过类型检查问题
            try:
                # 尝试迭代结果
                for item in matched_keys:
                    if isinstance(item, bytes):
                        result.append(item.decode('utf-8'))
                    else:
                        result.append(str(item))
            except Exception as iter_error:
                # 如果迭代失败，记录错误并返回空列表
                logger.warning(f"无法迭代Redis keys结果: {str(iter_error)}")
                pass
            return result
        except Exception as e:
            logger.error(f"Redis获取匹配键失败: {str(e)}")
            return []
    
    @staticmethod
    def close() -> None:
        """关闭Redis连接"""
        global _redis_client
        if _redis_client:
            try:
                _redis_client.close()
                _redis_client = None
                logger.info("Redis连接已关闭")
            except Exception as e:
                logger.error(f"关闭Redis连接时发生错误: {str(e)}")